package com.hkts.naturalgas.curvesettings.service.serviceimpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hkts.naturalgas.curvesettings.entity.CurveSettings;
import com.hkts.naturalgas.curvesettings.entity.HktsPowerFailure;
import com.hkts.naturalgas.curvesettings.mapper.HktsPowerFailureMapper;
import com.hkts.naturalgas.curvesettings.service.ICurveSettingsService;
import com.hkts.naturalgas.curvesettings.service.ICurveStateService;
import com.hkts.naturalgas.curvesettings.service.IHktsPowerFailureService;
import com.hkts.naturalgas.datahandler.constance.EnviromentConstance;
import com.hkts.naturalgas.datahandler.constance.PowerFailureConstance;
import com.hkts.naturalgas.datahandler.curvecache.CurveCache;
import com.hkts.naturalgas.datahandler.utils.GetRandomUtils;
import com.hkts.naturalgas.dictionaries.entity.HktsEnvironmentProtectionDictionaries;
import com.hkts.naturalgas.dictionaries.entity.HktsEnvironmentProtectionItem;
import com.hkts.naturalgas.dictionaries.utils.DBUtils;
import com.hkts.naturalgas.utils.SnowFlakeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yck
 * @since 2021-10-26
 */
@Service
@Transactional
public class HktsPowerFailureServiceImpl extends ServiceImpl<HktsPowerFailureMapper, HktsPowerFailure> implements IHktsPowerFailureService {
    @Autowired
    public DBUtils dBUtils;

    @Autowired
    private HktsPowerFailureMapper hktsPowerFailureMapper;
    @Autowired
    public ICurveSettingsService iCurveSettingsService;
    @Autowired
    public ICurveStateService iCurveStateService;

    @Override
    public IPage<HktsPowerFailure> selectPage(Page<HktsPowerFailure> page, HktsPowerFailure hktsPowerFailure) {
        QueryWrapper<HktsPowerFailure> query = Wrappers.query();
        QueryWrapper<HktsPowerFailure> entityWrapper = getEntityWrapper(query, hktsPowerFailure);
        return hktsPowerFailureMapper.selectPage(page, entityWrapper);
    }


    @Override
    public List<HktsPowerFailure> selectList(HktsPowerFailure hktsPowerFailure) {
        QueryWrapper<HktsPowerFailure> query = Wrappers.query();
        QueryWrapper<HktsPowerFailure> entityWrapper = getEntityWrapper(query, hktsPowerFailure);
        return hktsPowerFailureMapper.selectList(entityWrapper);
    }

    /**
     * 公共查询条件
     *
     * @param entityWrapper
     * @return
     */
    public QueryWrapper<HktsPowerFailure> getEntityWrapper(QueryWrapper<HktsPowerFailure> entityWrapper, HktsPowerFailure hktsPowerFailure) {
        //条件拼接
        if (StringUtils.isNotBlank(hktsPowerFailure.getPowerFailureCode())) {
            entityWrapper.like(HktsPowerFailure.POWER_FAILURE_CODE, hktsPowerFailure.getPowerFailureCode());
        }

        return entityWrapper;
    }

    @Override
    public Map<String, List<CurveSettings>> handlerPowerFailure(String powerFailure,
                                                                List<HktsEnvironmentProtectionDictionaries> hktsEnvironmentProtectionDictionaries,
                                                                Map<String, List<HktsEnvironmentProtectionItem>> itemMap,
                                                                Map<String, List<CurveSettings>> curveSettingMap,
                                                                LocalDateTime powerFailTime
    ) throws ParseException {
        QueryWrapper<HktsPowerFailure> query = Wrappers.query();
        HktsPowerFailure one = this.getOne(query);
        LocalDateTime now = LocalDateTime.now();
        //判断是否修改 如果修改需要更新流程缓存
        boolean isUpdate = false;

        //判断当前状态是否为正常
        if (powerFailure.equals(PowerFailureConstance.SYSTEM_NORMAL)) {
            if (one.getPowerFailureCode().equals(PowerFailureConstance.POWER_FAILURE)) {
                //修改曲线流程
               // updateCurveSettings(hktsEnvironmentProtectionDictionaries, curveSettingMap, one.getStopTime());
                //修改温度
                updateTempature(hktsEnvironmentProtectionDictionaries, itemMap, curveSettingMap, one.getStopTime());
                //根据状态修改
                one.setPowerFailureCode(PowerFailureConstance.SYSTEM_NORMAL);
                hktsPowerFailureMapper.updateById(one);
                isUpdate = true;
            } else if (one.getPowerFailureCode().equals(PowerFailureConstance.GAS_FAILURE)) {
                //修改曲线流程
                //updateCurveSettings(hktsEnvironmentProtectionDictionaries, curveSettingMap, one.getStopTime());
                one.setPowerFailureCode(PowerFailureConstance.SYSTEM_NORMAL);
                hktsPowerFailureMapper.updateById(one);
                isUpdate = true;
            }
        } else if (powerFailure.equals(PowerFailureConstance.POWER_FAILURE)) {
            if (one.getPowerFailureCode().equals(PowerFailureConstance.GAS_FAILURE)) {
                //updateCurveSettings(hktsEnvironmentProtectionDictionaries, curveSettingMap, one.getStopTime());
                one.setPowerFailureCode(PowerFailureConstance.POWER_FAILURE);
                one.setStopTime(now);
                hktsPowerFailureMapper.updateById(one);
                isUpdate = true;
            } else if (one.getPowerFailureCode().equals(PowerFailureConstance.SYSTEM_NORMAL)) {
                one.setPowerFailureCode(PowerFailureConstance.POWER_FAILURE);
                one.setStopTime(now);
                hktsPowerFailureMapper.updateById(one);
            }
        } else if (powerFailure.equals(PowerFailureConstance.GAS_FAILURE)) {
            if (one.getPowerFailureCode().equals(PowerFailureConstance.POWER_FAILURE)) {
                //修改曲线流程
                //updateCurveSettings(hktsEnvironmentProtectionDictionaries, curveSettingMap, one.getStopTime());
                //修改温度
                updateTempature(hktsEnvironmentProtectionDictionaries, itemMap, curveSettingMap, one.getStopTime());
                one.setPowerFailureCode(PowerFailureConstance.GAS_FAILURE);
                one.setStopTime(now);
                hktsPowerFailureMapper.updateById(one);
                isUpdate = true;
            } else if (one.getPowerFailureCode().equals(PowerFailureConstance.SYSTEM_NORMAL)) {
                one.setPowerFailureCode(PowerFailureConstance.GAS_FAILURE);
                one.setStopTime(now);
                hktsPowerFailureMapper.updateById(one);
                updateStopGasTempature(hktsEnvironmentProtectionDictionaries, itemMap, curveSettingMap, one.getStopTime());
            }else if(one.getPowerFailureCode().equals(PowerFailureConstance.GAS_FAILURE)){
                updateStopGasTempature(hktsEnvironmentProtectionDictionaries, itemMap, curveSettingMap, one.getStopTime());
            }
        }
        //更新定时任务的缓存
        if (isUpdate) {
            curveSettingMap = iCurveSettingsService.selectMapforShelder(hktsEnvironmentProtectionDictionaries);
        }
        return curveSettingMap;
    }

    public void updateCurveSettings(List<HktsEnvironmentProtectionDictionaries> hktsEnvironmentProtectionDictionaries,
                                    Map<String, List<CurveSettings>> curveSettingMap, LocalDateTime powerFailTime
    ) {
        java.time.Duration duration = java.time.Duration.between(powerFailTime, LocalDateTime.now());
        //停电后流程引擎不在往后跑时间往前推1倍，停气后时间还在往后跑所以需要乘2
        //停止时间到现在的秒数
        long seconds = duration.toMinutes() * 60;
        //停止时间到现在的速率
        float coolingRate = 1 / 60;
        List<CurveSettings> list = new ArrayList<>();
        for (int i = 0; i < hktsEnvironmentProtectionDictionaries.size(); i++) {
            if (StringUtils.isNotBlank(hktsEnvironmentProtectionDictionaries.get(i).getCurveId())) {
                List<CurveSettings> curveSettings = curveSettingMap.get(hktsEnvironmentProtectionDictionaries.get(i).getCurveId());
                boolean isStart = false;
                float temperatureVariation = (float) duration.toMinutes();
                for (int j = curveSettings.size() - 1; j >= 0; j--) {
                    //判断是否在倒数第二阶段
                    if (curveSettings.get(j).getCurrentNode().equals("1")) {
                        //用当前节点的时间，速度去折算需要向前推多少时间
                        if (j == curveSettings.size() - 1 || j == curveSettings.size() - 2) {
                            break;
                        } else {
                            isStart = true;
                            Integer currentSeconds = curveSettings.get(j).getCurrentSeconds();
                            Float rateSeconds = curveSettings.get(j).getRateSeconds();
                            if (currentSeconds * rateSeconds > temperatureVariation) {
                                int currentSecond = (int) (curveSettings.get(j).getCurrentSeconds() - temperatureVariation / rateSeconds);
                                curveSettings.get(j).setCurrentSeconds(currentSecond);
                                curveSettings.get(j).setCurrentNode(EnviromentConstance.IS_CURRENT_NODE);
                                isStart = false;
                            } else {
                                if(j==0){
                                    curveSettings.get(j).setCurrentSeconds(0);
                                    curveSettings.get(j).setCurrentNode(EnviromentConstance.IS_CURRENT_NODE);
                                }else{
                                    curveSettings.get(j).setCurrentSeconds(0);
                                    curveSettings.get(j).setCurrentNode(EnviromentConstance.IS_NOT_CURRENT_NODE);
                                    temperatureVariation = temperatureVariation - curveSettings.get(j).getCurrentSeconds() * rateSeconds;
                                }
                            }
                            list.add(curveSettings.get(j));
                        }
                    } else if (isStart) {
                        Integer currentSeconds = curveSettings.get(j).getTotalSeconds();
                        Float rateSeconds = curveSettings.get(j).getRateSeconds();
                        if (currentSeconds * rateSeconds > temperatureVariation) {
                            int currentSecond = (int) (curveSettings.get(j).getTotalSeconds() - temperatureVariation / rateSeconds);
                            curveSettings.get(j).setCurrentSeconds(currentSecond);
                            curveSettings.get(j).setCurrentNode(EnviromentConstance.IS_CURRENT_NODE);
                            list.add(curveSettings.get(j));
                            break;
                        } else {
                            if(j==0){
                                curveSettings.get(j).setCurrentSeconds(0);
                                curveSettings.get(j).setCurrentNode(EnviromentConstance.IS_CURRENT_NODE);
                                temperatureVariation = temperatureVariation - curveSettings.get(j).getCurrentSeconds() * rateSeconds;
                                list.add(curveSettings.get(j));
                            }else{
                                curveSettings.get(j).setCurrentSeconds(0);
                                curveSettings.get(j).setCurrentNode(EnviromentConstance.IS_NOT_CURRENT_NODE);
                                temperatureVariation = temperatureVariation - curveSettings.get(j).getTotalSeconds() * rateSeconds;
                                list.add(curveSettings.get(j));
                            }

                        }
                    }
                }
            }
        }
        iCurveSettingsService.updateBatchById(list);
    }

    /**
     * 功能描述:
     * 停电后电量推算
     *
     * @return: void
     * @Author: 杨春科
     * @Date: 2021-11-01 14:17
     * @Description //TODO
     */
    public void updateTempature(List<HktsEnvironmentProtectionDictionaries> hktsEnvironmentProtectionDictionaries,
                                Map<String, List<HktsEnvironmentProtectionItem>> itemMap,
                                Map<String, List<CurveSettings>> curveSettingMap, LocalDateTime powerFailTime
    ) throws ParseException {
        List<String> sqlList = new ArrayList<>();
        //计算时间差
        java.time.Duration duration = java.time.Duration.between(powerFailTime, LocalDateTime.now());
        long minute = duration.toMinutes();
        String id = String.valueOf(SnowFlakeUtil.getFlowIdInstance().nextId());
        //
        for (int i = 0; i < hktsEnvironmentProtectionDictionaries.size(); i++) {
            Map<String, Object> lastRow = dBUtils.getLastRow(hktsEnvironmentProtectionDictionaries.get(i).getTableName());
            CurveCache.lastRowCache.remove(hktsEnvironmentProtectionDictionaries.get(i).getTableName());
            List<HktsEnvironmentProtectionItem> hktsEnvironmentProtectionItems = itemMap.get(hktsEnvironmentProtectionDictionaries.get(i).getId());
            for (int j = 0; j < hktsEnvironmentProtectionItems.size(); j++) {
                Object lastValue = lastRow.get(hktsEnvironmentProtectionItems.get(j).getFieldName());
                if (!hktsEnvironmentProtectionItems.get(j).getDataType().equals(EnviromentConstance.DATE_TIME)) {
                    if (lastValue != null && Float.parseFloat(lastValue.toString()) != 0) {
                        if(Float.parseFloat(lastValue.toString())<50){
                            lastRow.put(hktsEnvironmentProtectionItems.get(j).getFieldName(), Float.parseFloat(lastValue.toString()) );
                        }else{
                            lastRow.put(hktsEnvironmentProtectionItems.get(j).getFieldName(), Float.parseFloat(lastValue.toString()) - minute);
                        }

                    }
                }

            }
            sqlList.add(dBUtils.updateSql(hktsEnvironmentProtectionDictionaries.get(i).getTableName(), hktsEnvironmentProtectionItems, lastRow, id));
        }
        dBUtils.updateBatch(sqlList);
    }
    public void updateStopGasTempature(List<HktsEnvironmentProtectionDictionaries> hktsEnvironmentProtectionDictionaries,
                                Map<String, List<HktsEnvironmentProtectionItem>> itemMap,
                                Map<String, List<CurveSettings>> curveSettingMap, LocalDateTime powerFailTime
    ) throws ParseException {
        List<String> sqlList = new ArrayList<>();
        //计算时间差
        java.time.Duration duration = java.time.Duration.between(powerFailTime, LocalDateTime.now());
        long minute = duration.toMinutes();
        float temperatureVariation=0;
        String id = String.valueOf(SnowFlakeUtil.getFlowIdInstance().nextId());
        //
        for (int i = 0; i < hktsEnvironmentProtectionDictionaries.size(); i++) {
            Map<String, Object> lastRow = dBUtils.getLastRow(hktsEnvironmentProtectionDictionaries.get(i).getTableName());
            CurveCache.lastRowCache.remove(hktsEnvironmentProtectionDictionaries.get(i).getTableName());
            List<HktsEnvironmentProtectionItem> hktsEnvironmentProtectionItems = itemMap.get(hktsEnvironmentProtectionDictionaries.get(i).getId());
            for (int j = 0; j < hktsEnvironmentProtectionItems.size(); j++) {
                Object lastValue = lastRow.get(hktsEnvironmentProtectionItems.get(j).getFieldName());
                if (!hktsEnvironmentProtectionItems.get(j).getDataType().equals(EnviromentConstance.DATE_TIME)) {
                    if (lastValue != null && Float.parseFloat(lastValue.toString()) != 0) {
                        lastRow.put(hktsEnvironmentProtectionItems.get(j).getFieldName(), Float.parseFloat(lastValue.toString()) - GetRandomUtils.getDownTemperature());
                    }
                }

            }
            sqlList.add(dBUtils.updateSql(hktsEnvironmentProtectionDictionaries.get(i).getTableName(), hktsEnvironmentProtectionItems, lastRow, id));
        }
        dBUtils.updateBatch(sqlList);
    }
}
